<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <!-- setState -->
  <title>Title</title>
  <!-- 1）引入react.js  核心  类似于vue.js -->
  <script src="./libs/react.development.js"></script>
  <!-- 2）引入react-dom.js  提供了DOM操作的扩展库-->
  <script src="./libs/react-dom.development.js"></script>
  <!-- 3）引入babel.js  可以把jsx转成浏览器可以识别的语法 -->
  <script src="./libs/babel.js"></script>
</head>

<body>

  <div id="app"></div>

  <script type="text/babel">

    class DemoA extends React.Component {
      constructor(props) {
        super(props)
        // 定义状态
        // 1）在constructor中定义状态
        this.state = {
          // 定义的数据是不可变值（数据）
          count: 0
        }
      }
      add = () => {
        // 2）修改状态，需要通过专属方法，叫stState
        // 不是直接去修改  this.state.count++ // 并不会导致页面刷新
        // this.setState({
        //   count: this.state.count + 1
        //   // 修改了两个次状态：a)this.state.count++  b)this.setState间接修改了
        //   // count: this.state.count++
        // })

        // 3)setState是同步的还是异步的（有可能是同步，有可能是异步的）
        // setState直接暴露在react的合成事件中，是异步
        // this.setState({
        //   count: this.state.count + 1
        // }, () => {
        //   // vue中的nextTick
        //   console.log("count by callback:", this.state.count);
        // })
        // // 异步的，拿不到最新的值
        // console.log("count:", this.state.count);

        // setState中setTimeout中同步的
        setTimeout(() => {
          this.setState({
            count: this.state.count + 1
          })
          this.setState({
            count: this.state.count + 1
          })
          this.setState({
            count: this.state.count + 1
          })
          this.setState({
            count: this.state.count + 1
          })
          console.log("count:", this.state.count);
        }, 1)

        // 4)setState合并问题,传入对象才会出现合并问题
        // 最终结果只会+1   类似于Object.assgin
        // this.setState({
        //   count: this.state.count + 1
        // })
        // this.setState({
        //   count: this.state.count + 1
        // })
        // this.setState({
        //   count: this.state.count + 1
        // })

        // setState传入的是一个函数，不存在合并问题
        // 最终结果是+3
        // this.setState((state, props) => {
        //   return {
        //     count: state.count + 1
        //   }
        // })
        // this.setState((state, props) => {
        //   return {
        //     count: state.count + 1
        //   }
        // })
        // this.setState((state, props) => {
        //   return {
        //     count: state.count + 1
        //   }
        // })
      }
      render() {
        return (
          <div>
            <h1>类组件</h1>
            <h2>{this.state.count}</h2>
            <button onClick={this.add}>+1</button>
          </div>
        )
      }
      // setState出现在原生DOM事件中，也是同步的
      // clickHandler = () => {
      //   this.setState({
      //     count: this.state.count + 1
      //   })
      //   console.log("count:", this.state.count);
      // }
      // componentDidMount() {
      //   document.body.addEventListener("click", this.clickHandler)
      // }
      // componentWillUnmount() {
      //   // 即使销毁DOM事件
      //   document.body.removeEventListener("click", this.clickHandler)
      // }
    };

    class DemoB extends React.Component {
      constructor(props) {
        super(props)
        this.state = {
          count: 0
        }
      }
      render() {
        return <p>{this.state.count}</p>
      }
      componentDidMount() {
        this.setState({ count: this.state.count + 1 })
        console.log('1', this.state.count)
        this.setState({ count: this.state.count + 1 })
        console.log('2', this.state.count)
        setTimeout(() => {
          this.setState({ count: this.state.count + 1 })
          console.log('3', this.state.count)
        })
        setTimeout(() => {
          this.setState({ count: this.state.count + 1 })
          console.log('4', this.state.count)
        })
      }
    }
    ReactDOM.render(<DemoB />, document.getElementById("app"))
  </script>

</body>

</html>

<!-- 
  setState在16中：
    setState直接暴露在React的合成事件中异步的，传入的是对象，会合并，传入的是函数，不会合并 
    setState出现在定时器，或DOM事件中是同步的，不会合并

  在react18版本中：
    不管setState出现在任何方都是异步的。都会合并state。
 -->